home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / security / SecureRandom.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  15.3 KB  |  461 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)SecureRandom.java    1.30 98/08/24
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.Enumeration;
  18.  
  19. /**
  20.  * <p>This class provides a cryptographically strong pseudo-random number
  21.  * generator (PRNG).
  22.  *
  23.  * <p>Like other algorithm-based classes in Java Security, SecureRandom 
  24.  * provides implementation-independent algorithms, whereby a caller 
  25.  * (application code) requests a particular PRNG algorithm
  26.  * and is handed back a SecureRandom object for that algorithm. It is
  27.  * also possible, if desired, to request a particular algorithm from a
  28.  * particular provider. See the <code>getInstance</code> methods.
  29.  *
  30.  * <p>Thus, there are two ways to request a SecureRandom object: by
  31.  * specifying either just an algorithm name, or both an algorithm name
  32.  * and a package provider.
  33.  *
  34.  * <ul>
  35.  *
  36.  * <li>If just an algorithm name is specified, as in:
  37.  * <pre>
  38.  *      SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
  39.  * </pre>
  40.  * the system will determine if there is an implementation of the algorithm
  41.  * requested available in the environment, and if there is more than one, if
  42.  * there is a preferred one.<p>
  43.  * 
  44.  * <li>If both an algorithm name and a package provider are specified, as in:
  45.  * <pre>
  46.  *      SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
  47.  * </pre>
  48.  * the system will determine if there is an implementation of the
  49.  * algorithm in the package requested, and throw an exception if there
  50.  * is not.
  51.  *
  52.  * </ul>
  53.  *
  54.  * <p>The SecureRandom implementation attempts to completely
  55.  * randomize the internal state of the generator itself unless
  56.  * the caller follows the call to a <code>getInstance</code> method
  57.  * with a call to the <code>setSeed</code> method:
  58.  * <pre>
  59.  *      SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
  60.  *      random.setSeed(seed);
  61.  * </pre>
  62.  *
  63.  * <p>After the caller obtains the SecureRandom object from the
  64.  * <code>getInstance</code> call, it can call <code>nextBytes</code>
  65.  * to generate random bytes:
  66.  * <pre>
  67.  *      byte bytes[] = new byte[20];
  68.  *      random.nextBytes(bytes);
  69.  * </pre>
  70.  *
  71.  * <p>The caller may also invoke the <code>generateSeed</code> method
  72.  * to generate a given number of seed bytes (to seed other random number
  73.  * generators, for example):
  74.  * <pre>
  75.  *      byte seed[] = random.generateSeed(20);
  76.  * </pre>
  77.  *
  78.  * @see java.security.SecureRandomSpi
  79.  * @see java.util.Random
  80.  * 
  81.  * @version 1.30, 99/03/26
  82.  * @author Benjamin Renaud
  83.  * @author Josh Bloch 
  84.  */
  85.  
  86. public class SecureRandom extends java.util.Random {
  87.  
  88.     /**
  89.      * The provider.
  90.      *
  91.      * @serial
  92.      * @since JDK 1.2
  93.      */
  94.     private Provider provider = null;
  95.  
  96.     /**
  97.      * The provider implementation.
  98.      *
  99.      * @serial
  100.      * @since JDK 1.2
  101.      */
  102.     private SecureRandomSpi secureRandomSpi = null;
  103.  
  104.     // Seed Generator
  105.     private static SecureRandom seedGenerator = null;
  106.  
  107.     /**
  108.      * <p>By using this constructor, the caller obtains a SecureRandom object
  109.      * containing the implementation from the highest-priority installed
  110.      * provider that has a SecureRandom implementation.
  111.      * 
  112.      * <p>Note that this instance of SecureRandom has not been seeded.
  113.      * A call to the <code>setSeed</code> method will seed the SecureRandom
  114.      * object.  If a call is not made to <code>setSeed</code>, the first call
  115.      * to the <code>nextBytes</code> method will force the SecureRandom object
  116.      * to seed itself.
  117.      *
  118.      * <p>This constructor is provided for backwards compatibility. 
  119.      * The caller is encouraged to use one of the alternative
  120.      * <code>getInstance</code> methods to obtain a SecureRandom object.
  121.      */
  122.     public SecureRandom() {
  123.     /*
  124.      * This call to our superclass constructor will result in a call
  125.      * to our own <code>setSeed</code> method, which will return
  126.      * immediately when it is passed zero.
  127.      */
  128.     super(0);
  129.     String prng = getPrngAlgorithm();
  130.     if (prng == null) {
  131.         // bummer, get the SUN implementation
  132.         this.secureRandomSpi = new sun.security.provider.SecureRandom();
  133.         this.provider = new sun.security.provider.Sun();
  134.     } else {
  135.         try {
  136.         SecureRandom random = SecureRandom.getInstance(prng);
  137.         this.secureRandomSpi = random.getSecureRandomSpi();
  138.         this.provider = random.getProvider();
  139.         } catch (NoSuchAlgorithmException nsae) {
  140.         // never happens, because we made sure the algorithm exists
  141.         }
  142.     }
  143.     }
  144.  
  145.     /**
  146.      * <p>By using this constructor, the caller obtains a SecureRandom object
  147.      * containing the implementation from the highest-priority installed
  148.      * provider that has a SecureRandom implementation. This constructor 
  149.      * uses a user-provided seed in
  150.      * preference to the self-seeding algorithm referred to in the empty
  151.      * constructor description. It may be preferable to the empty constructor
  152.      * if the caller has access to high-quality random bytes from some physical
  153.      * device (for example, a radiation detector or a noisy diode).
  154.      * 
  155.      * <p>This constructor is provided for backwards compatibility. 
  156.      * The caller is encouraged to use one of the alternative
  157.      * <code>getInstance</code> methods to obtain a SecureRandom object, and
  158.      * then to call the <code>setSeed</code> method to seed it.
  159.      * 
  160.      * @param seed the seed.
  161.      */
  162.     public SecureRandom(byte seed[]) {
  163.     super(0);
  164.     String prng = getPrngAlgorithm();
  165.     if (prng == null) {
  166.         // bummer, get the SUN implementation
  167.         this.secureRandomSpi = new sun.security.provider.SecureRandom();
  168.         this.provider = new sun.security.provider.Sun();
  169.         this.secureRandomSpi.engineSetSeed(seed);
  170.     } else {
  171.         try {
  172.         SecureRandom random = getInstance(prng);
  173.         this.secureRandomSpi = random.getSecureRandomSpi();
  174.         this.provider = random.getProvider();
  175.         this.secureRandomSpi.engineSetSeed(seed);
  176.         } catch (NoSuchAlgorithmException nsae) {
  177.         // never happens, because we made sure the algorithm exists
  178.         }
  179.     }
  180.     }
  181.  
  182.     /**
  183.      * Creates a SecureRandom object.
  184.      *
  185.      * @param secureRandomSpi the SecureRandom implementation.
  186.      * @param provider the provider.
  187.      */
  188.     protected SecureRandom(SecureRandomSpi secureRandomSpi,
  189.                Provider provider) {
  190.     super(0);
  191.     this.secureRandomSpi = secureRandomSpi;
  192.     this.provider = provider;
  193.     }
  194.  
  195.     /**
  196.      * Generates a SecureRandom object that implements the specified
  197.      * Pseudo Random Number Generator (PRNG) algorithm. If the default
  198.      * provider package provides an implementation of the requested PRNG,
  199.      * an instance of SecureRandom containing that implementation is returned.
  200.      * If the PRNG is not available in the default 
  201.      * package, other packages are searched.
  202.      *
  203.      * <p>Note that the returned instance of SecureRandom has not been seeded.
  204.      * A call to the <code>setSeed</code> method will seed the SecureRandom
  205.      * object.  If a call is not made to <code>setSeed</code>, the first call
  206.      * to the <code>nextBytes</code> method will force the SecureRandom object
  207.      * to seed itself.
  208.      *
  209.      * @param algorithm the name of the PRNG algorithm.
  210.      * See Appendix A in the <a href=
  211.      * "../../../guide/security/CryptoSpec.html#AppA">
  212.      * Java Cryptography Architecture API Specification & Reference </a> 
  213.      * for information about standard PRNG algorithm names.
  214.      *
  215.      * @return the new SecureRandom object.
  216.      *
  217.      * @exception NoSuchAlgorithmException if the PRNG algorithm is
  218.      * not available in the caller's environment.
  219.      *
  220.      * @since JDK1.2
  221.      */
  222.     public static SecureRandom getInstance(String algorithm)
  223.     throws NoSuchAlgorithmException {
  224.         try {
  225.         Object[] objs = Security.getImpl(algorithm,
  226.                          "SecureRandom",
  227.                          null);
  228.         return new SecureRandom((SecureRandomSpi)objs[0],
  229.                     (Provider)objs[1]);
  230.         } catch(NoSuchProviderException e) {
  231.         throw new NoSuchAlgorithmException(algorithm + " not found");
  232.         }
  233.     }
  234.  
  235.     /**
  236.      * Generates a SecureRandom object for the specified PRNG
  237.      * algorithm, as supplied from the specified provider, if such a
  238.      * PRNG implementation is available from the provider.
  239.      *
  240.      * <p>Note that the returned instance of SecureRandom has not been seeded.
  241.      * A call to the <code>setSeed</code> method will seed the SecureRandom
  242.      * object.  If a call is not made to <code>setSeed</code>, the first call
  243.      * to the <code>nextBytes</code> method will force the SecureRandom object
  244.      * to seed itself.
  245.      *
  246.      * @param algorithm the name of the PRNG algorithm.
  247.      * See Appendix A in the <a href=
  248.      * "../../../guide/security/CryptoSpec.html#AppA">
  249.      * Java Cryptography Architecture API Specification & Reference </a> 
  250.      * for information about standard PRNG algorithm names.
  251.      *
  252.      * @param provider the name of the provider.
  253.      *
  254.      * @return the new SecureRandom object.
  255.      *
  256.      * @exception NoSuchAlgorithmException if the requested PRNG
  257.      * implementation is not available from the provider.
  258.      *
  259.      * @exception NoSuchProviderException if the provider has not been
  260.      * configured.
  261.      *
  262.      * @see Provider
  263.      *
  264.      * @since JDK1.2
  265.      */
  266.     public static SecureRandom getInstance(String algorithm, String provider)
  267.     throws NoSuchAlgorithmException, NoSuchProviderException
  268.     {
  269.     if (provider == null || provider.length() == 0)
  270.         throw new IllegalArgumentException("missing provider");
  271.     Object[] objs = Security.getImpl(algorithm, "SecureRandom", provider);
  272.     return new SecureRandom((SecureRandomSpi)objs[0], (Provider)objs[1]);
  273.     }
  274.  
  275.     /**
  276.      * Returns the SecureRandomSpi of this SecureRandom object.
  277.      */
  278.     SecureRandomSpi getSecureRandomSpi() {
  279.     return secureRandomSpi;
  280.     }
  281.  
  282.     /**
  283.      * Returns the provider of this SecureRandom object.
  284.      *
  285.      * @return the provider of this SecureRandom object.
  286.      */
  287.     public final Provider getProvider() {
  288.     return provider;
  289.     }
  290.  
  291.     /**
  292.      * Reseeds this random object. The given seed supplements, rather than
  293.      * replaces, the existing seed. Thus, repeated calls are guaranteed
  294.      * never to reduce randomness.
  295.      *
  296.      * @param seed the seed.
  297.      */
  298.     synchronized public void setSeed(byte[] seed) {
  299.     secureRandomSpi.engineSetSeed(seed);
  300.     }
  301.  
  302.     /**
  303.      * Reseeds this random object, using the eight bytes contained 
  304.      * in the given <code>long seed</code>. The given seed supplements, 
  305.      * rather than replaces, the existing seed. Thus, repeated calls 
  306.      * are guaranteed never to reduce randomness. 
  307.      * 
  308.      * <p>This method is defined for compatibility with 
  309.      * <code>java.util.Random</code>.
  310.      *
  311.      * @param seed the seed.
  312.      */
  313.     public void setSeed(long seed) {
  314.     /* 
  315.      * Ignore call from super constructor (as well as any other calls
  316.      * unfortunate enough to be passing 0).  It's critical that we
  317.      * ignore call from superclass constructor, as digest has not
  318.      * yet been initialized at that point.
  319.      */
  320.     if (seed != 0)
  321.         secureRandomSpi.engineSetSeed(longToByteArray(seed));
  322.     }
  323.  
  324.     /**
  325.      * Generates a user-specified number of random bytes.  This method is
  326.      * used as the basis of all random entities returned by this class
  327.      * (except seed bytes).
  328.      * 
  329.      * @param bytes the array to be filled in with random bytes.
  330.      */
  331.  
  332.     synchronized public void nextBytes(byte[] bytes) {
  333.     secureRandomSpi.engineNextBytes(bytes);
  334.     }
  335.  
  336.     /**
  337.      * Generates an integer containing the user-specified number of
  338.      * pseudo-random bits (right justified, with leading zeros).  This
  339.      * method overrides a <code>java.util.Random</code> method, and serves
  340.      * to provide a source of random bits to all of the methods inherited
  341.      * from that class (for example, <code>nextInt</code>,
  342.      * <code>nextLong</code>, and <code>nextFloat</code>).
  343.      *
  344.      * @param numBits number of pseudo-random bits to be generated, where
  345.      * 0 <= <code>numBits</code> <= 32.
  346.      */
  347.     final protected int next(int numBits) {
  348.     int numBytes = (numBits+7)/8;
  349.     byte b[] = new byte[numBytes];
  350.     int next = 0;
  351.  
  352.     nextBytes(b);
  353.     for (int i=0; i<numBytes; i++)
  354.         next = (next << 8) + (b[i] & 0xFF);
  355.  
  356.     return next >>> (numBytes*8 - numBits);
  357.     }
  358.  
  359.     /**
  360.      * Returns the given number of seed bytes, computed using the seed
  361.      * generation algorithm that this class uses to seed itself.  This
  362.      * call may be used to seed other random number generators.
  363.      *
  364.      * <p>This method is only included for backwards compatibility. 
  365.      * The caller is encouraged to use one of the alternative
  366.      * <code>getInstance</code> methods to obtain a SecureRandom object, and
  367.      * then call the <code>generateSeed</code> method to obtain seed bytes
  368.      * from that object.
  369.      *
  370.      * @param numBytes the number of seed bytes to generate.
  371.      * 
  372.      * @return the seed bytes.
  373.      */
  374.      public static byte[] getSeed(int numBytes) {
  375.     if (seedGenerator == null)
  376.         seedGenerator = new SecureRandom();
  377.     return seedGenerator.generateSeed(numBytes);
  378.      }
  379.  
  380.     /**
  381.      * Returns the given number of seed bytes, computed using the seed
  382.      * generation algorithm that this class uses to seed itself.  This
  383.      * call may be used to seed other random number generators.
  384.      *
  385.      * @param numBytes the number of seed bytes to generate.
  386.      * 
  387.      * @return the seed bytes.
  388.      */
  389.     public byte[] generateSeed(int numBytes) {
  390.     return secureRandomSpi.engineGenerateSeed(numBytes);
  391.     }
  392.  
  393.     /**
  394.      * Helper function to convert a long into a byte array (least significant
  395.      * byte first).
  396.      */
  397.     private static byte[] longToByteArray(long l) {
  398.     byte[] retVal = new byte[8];
  399.  
  400.     for (int i=0; i<8; i++) {
  401.         retVal[i] = (byte) l;
  402.         l >>= 8;
  403.     }
  404.  
  405.     return retVal;
  406.     }
  407.  
  408.     /**
  409.      * Gets a default PRNG algorithm by looking through all registered
  410.      * providers. Returns the first PRNG algorithm of the first provider that
  411.      * has registered a SecureRandom implementation, or null if none of the
  412.      * registered providers supplies a SecureRandom implementation.
  413.      */
  414.     private static String getPrngAlgorithm() {
  415.     Provider[] provs = Security.getProviders();
  416.     for (int i=0; i<provs.length; i++) {
  417.         // search the provider's properties list for a property name
  418.         // that starts with "SecureRandom."
  419.         for (Enumeration e = provs[i].propertyNames();
  420.          e.hasMoreElements();) {
  421.         String propName = (String)e.nextElement();
  422.         if (propName.startsWith("SecureRandom.")) {
  423.             int index = propName.indexOf(".", 0);
  424.             return propName.substring(index+1);
  425.         }
  426.         }
  427.     }
  428.     return null;
  429.     }
  430.  
  431.     // Declare serialVersionUID to be compatible with JDK1.1
  432.     static final long serialVersionUID = 4940670005562187L;
  433.  
  434.     // Retain unused values serialized from JDK1.1
  435.     /**
  436.      * @serial
  437.      */
  438.     private byte[] state;
  439.     /**
  440.      * @serial
  441.      */
  442.     private MessageDigest digest = null;
  443.     /**
  444.      * @serial
  445.      *
  446.      * We know that the MessageDigest class does not implement
  447.      * java.io.Serializable.  However, since this field is no longer
  448.      * used, it will always be NULL and won't affect the serialization
  449.      * of the SecureRandom class itself.
  450.      */
  451.     private byte[] randomBytes;
  452.     /**
  453.      * @serial
  454.      */
  455.     private int randomBytesUsed;
  456.     /**
  457.      * @serial
  458.      */
  459.     private long counter;
  460. }
  461.